/*
 * proceso.cpp
 *
 *  Created on: Oct 29, 2013
 *      Author: m
 */

#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include "CPrinter.h"
#include "NewSharedMemory.h"
#include "NewSemaphore.h"
#include "Sequence.h"
#include "DefinicionesComunes.h"

using namespace ipc;

int main( int argc, char* argv[] )
{
    int id;
    int maxProcEsp;
    std::stringstream ss;

    srand( time( NULL ) );

    SharedMemory<int> shmNProcesosEspera = SharedMemory<int>::get( BASE_FILE, SHM_CONTADOR );
    SharedMemory<int> shmDatos = SharedMemory<int>::get( BASE_FILE, SHM_DATOS );
    Semaphore semProceso = Semaphore::get( BASE_FILE, SEM_PROCESO );
    Semaphore mutexNProcesosEspera = Semaphore::get( BASE_FILE, MUTEX_CONTADOR );
    Sequence idSequence = Sequence::get( BASE_FILE, SEQ_ID );

    // Parseo argumentos
    // argv[1] : Cantidad de procesos en la barrera
    if ( argc != 2 )
    {
        CPrinter::printErr( "Argumentos Invalidos.\n"
                "USO:\t\t proceso [cantidad total procesos]." );
        exit( 1 );
    }
    else
    {
        ss << argv[1];
        ss >> maxProcEsp;
    }

    // Obtengo el ID
    id = idSequence.getNext();

    // Inicializo el CPrinter
    CPrinter::setHeader( "proceso", id );

    for ( int i = 1; i <= 100; i++ )
    {
        sleep( random() % 5 );

        int nProcEsp;

        shmDatos.write( i, id - 1 );

        CPrinter::printOut( "escrito: %d", i );

        mutexNProcesosEspera.p();

        nProcEsp = shmNProcesosEspera.read();

        nProcEsp++;

        shmNProcesosEspera.write( nProcEsp );

        if ( nProcEsp < maxProcEsp )
        {
            mutexNProcesosEspera.v();
            semProceso.p( id - 1 );
        }
        else
        {
            shmNProcesosEspera.write( 0 );
            mutexNProcesosEspera.v();

            for ( int j = 0; j < maxProcEsp; j++ )
            {
                if ( j != id - 1 )
                {
                    semProceso.v( j );
                }
            }
        }
    }

    CPrinter::printOut( "fin" );

    return 0;
}
